package com.example.demo.service.impl;

import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.demo.bean.PageRes;
import com.example.demo.bean.sysfile.SysFileCateDO;
import com.example.demo.bean.sysfile.SysFileDO;
import com.example.demo.config.MyConfig;
import com.example.demo.enums.FileTypeEnum;
import com.example.demo.enums.SysTypeEnum;
import com.example.demo.exception.OtherException;
import com.example.demo.mapper.sysfile.SysFileCateMapper;
import com.example.demo.mapper.sysfile.SysFileMapper;
import com.example.demo.service.ISysFileService;
import com.example.demo.dto.sysfile.SysFilePageReqVO;
import jakarta.annotation.Resource;
import org.dromara.x.file.storage.core.FileInfo;
import org.springframework.stereotype.Service;

import java.io.File;
import java.net.URI;
import java.net.URISyntaxException;

@Service
public class SysFileServiceImpl extends ServiceImpl<SysFileMapper, SysFileDO> implements ISysFileService {

    @Resource
    private SysFileMapper sysFileMapper;

    @Resource
    private SysFileCateMapper sysFileCateMapper;

    @Override
    public PageRes<SysFileDO> list(SysFilePageReqVO sysFileCatePageReqVO) {
        return sysFileCatePageReqVO.getPageSize() == -1
                ? sysFileMapper.selectNotPage(sysFileCatePageReqVO)
                : sysFileMapper.selectPage(sysFileCatePageReqVO);
    }

    @Override
    public int addSysFile(Long cid, Integer type, FileInfo fileInfo) {
        validCateExist(cid);
        validUploadSuccess(fileInfo);
        validTypeIllegal(type);
        validFileTypeMatched(type, fileInfo);

        // 构造存储文件参数
        try {
            SysFileDO sysFileDO = new SysFileDO()
                    .setCid(cid)
                    .setType(type)
                    .setSource(SysTypeEnum.ADMIN.value())
                    .setName(fileInfo.getFilename())
                    .setUri(new URI(fileInfo.getUrl()).getPath());
            return sysFileMapper.insert(sysFileDO);
        } catch (URISyntaxException e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public int renameSysFile(SysFileDO sysFileDO) {
        validFileExist(sysFileDO.getId());
        return sysFileMapper.updateById(sysFileDO);
    }

    @Override
    public int moveSysFile(Long[] fileIds,SysFileDO sysFileDO) {
        int moveCount = 0;
        for (Long fileId : fileIds){
            validFileExist(fileId);
            validCateExist(sysFileDO.getCid());
            validFileTypeMatched(sysFileDO.getCid(),sysFileDO.getType());
            SysFileDO update = new SysFileDO().setId(fileId).setCid(sysFileDO.getCid());
            moveCount += sysFileMapper.updateById(update);
        }
        return moveCount;
    }

    @Override
    public int deleteSysFile(Long[] fileIds) {
        int deletedCount = 0;
        for (Long fileId : fileIds){
            validFileExist(fileId);
            // 删除本地文件
            SysFileDO fileInfo = sysFileMapper.selectById(fileId);
            File file = new File(MyConfig.getStoragePath() + fileInfo.getUri().replace(MyConfig.getFilePatterns(), ""));
            if(file.isFile() && file.exists()){
                file.delete();
                deletedCount += sysFileMapper.deleteById(fileId);
            }else{
                throw new OtherException("文件不存在或删除资源不是文件类型");
            }
        }
        return deletedCount;
    }

    @Override
    public SysFileDO getSysFile(SysFileDO sysFileDO) {
        validFileExist(sysFileDO.getId());
        return sysFileMapper.selectById(sysFileDO.getId());
    }

    private void validUploadSuccess(FileInfo fileInfo) {
        if (fileInfo == null) {
            throw new OtherException("文件上传失败");
        }
    }

    private void validTypeIllegal(Integer type) {
        if (!FileTypeEnum.isValid(type)) {
            throw new OtherException("不合法的文件类型");
        }
    }

    private void validFileTypeMatched(Integer type, FileInfo fileInfo) {
        FileTypeEnum realType = FileTypeEnum.fromContentType(fileInfo.getContentType());
        if (realType == null) {
            deleteIllegalFile(fileInfo);
            throw new OtherException(StrUtil.format("不支持:{}类型文件", fileInfo.getContentType()));
        } else {
            if (!realType.value().equals(type)) {
                deleteIllegalFile(fileInfo);
                throw new OtherException("传入的type与文件实际类型不匹配");
            }
        }
    }

    private void validCateExist(Long cid) {
        SysFileCateDO exist = sysFileCateMapper.selectById(cid);
        if (exist == null && cid != 0) {
            throw new OtherException("文件分类不存在");
        }
    }

    private void validFileExist(Long id) {
        SysFileDO exist = sysFileMapper.selectById(id);
        if (exist == null) {
            throw new OtherException("文件不存在");
        } else {
            File existFile = new File(MyConfig.getStoragePath() + exist.getUri().replace(MyConfig.getFilePatterns(), ""));
            if(!existFile.exists()){
                throw new OtherException("文件不存在");
            }
        }
    }

    private void validFileTypeMatched(Long cid,Integer type){
        QueryWrapper<SysFileCateDO> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("id",cid);
        queryWrapper.eq("type",type);
        SysFileCateDO related = sysFileCateMapper.selectOne(queryWrapper);
        if(related == null){
            throw new OtherException("不能跨文件类型移动");
        }
    }

    private void deleteIllegalFile(FileInfo fileInfo){
        File file = new File(MyConfig.getStoragePath() + fileInfo.getUrl().replace(MyConfig.getDomain()+MyConfig.getFilePatterns(), ""));
        if(file.isFile() && file.exists()){
            file.delete();
        }
    }
}
